package com.ys.service.finance.impl;

import com.alibaba.fastjson.JSON;
import com.ys.dto.AddDto;
import com.ys.entity.finance.TcwDepositPlatform;
import com.ys.entity.finance.TcwWanliExchangeRate;
import com.ys.entity.sys.YsCol;
import com.ys.enume.finance.TcwWanliPayoutEnum;
import com.ys.mapper.finance.FinanceMapper;
import com.ys.mapper.finance.TcwWanliExchangeRateMapper;
import com.ys.service.finance.TcwWanliExchangeRateService;
import com.ys.util.CheckUtil;
import com.ys.util.DateUtil;
import com.ys.vo.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 万里汇CNY计算汇率表
 */
@Service("tcwWanliExchangeRateService")
public class TcwWanliExchangeRateServiceImpl implements TcwWanliExchangeRateService {
	private static final Logger logger = LoggerFactory.getLogger(TcwWanliExchangeRateServiceImpl.class);

	@Autowired
	private TcwWanliExchangeRateMapper tcwWanliExchangeRateMapper;

	@Autowired
	private CheckUtil checkUtil;

	@Autowired
	private FinanceMapper financeMapper;

	/**
	 * 新增
	 */
	@Override
	public R add(Map<String, Object> params, Long menuId) throws Exception{
		logger.info("新增传参:"+params);
		//参数验证
		String errorBack = checkParams(params, menuId,ysColItem->ysColItem.getFormAddRequired()!=null && ysColItem.getFormAddRequired() == 1);
		if(errorBack!=null && !"".equals(errorBack)){
			return R.error(errorBack);
		}

		//获取收款平台信息
		TcwDepositPlatform tcwDepositPlatform = new TcwDepositPlatform().setMid(params.get("depositPlatformMid").toString()).queryFirst();
		if(tcwDepositPlatform==null){
			return R.error("无效的收款平台信息");
		}
		params.put("depositPlatformId",tcwDepositPlatform.getId());//平台id
		params.put("code",tcwDepositPlatform.getCode());//平台code

		//计算汇率
		List<Map<String, Object>> tcwWanliExchangeRateList = new ArrayList<>();
		tcwWanliExchangeRateList.add(params);
		List<TcwWanliExchangeRate> listByNew = getExchangeRateByList(tcwWanliExchangeRateList,false,params.get("countTimeStart").toString(),params.get("countTimeEnd").toString());
		//获取结果
		TcwWanliExchangeRate tcwWanliExchangeRate = listByNew.get(0);
		tcwWanliExchangeRate.setStatus(1);//状态
		tcwWanliExchangeRate.setTargetCurrencyCode("CNY");

		//新增
		tcwWanliExchangeRateMapper.insert(tcwWanliExchangeRate);

		//return R.ok(EditDto.closeAndReload());
		return R.ok(AddDto.gotoEdit("/web/finance/tcwWanliExchangeRate/toEdit?id=" + tcwWanliExchangeRate.getId()));
	}


	/**
	 * 修改
	 */
	@Override
	public R update(Map<String, Object> params, Long menuId) throws Exception{
		logger.info("修改传参:"+params);
		//参数验证
		String errorBack = checkParams(params, menuId,ysColItem->ysColItem.getFormEditRequired()!=null && ysColItem.getFormEditRequired() == 1);
		if(errorBack!=null && !"".equals(errorBack)){
			return R.error(errorBack);
		}
		TcwWanliExchangeRate tcwWanliExchangeRate = JSON.parseObject(JSON.toJSONString(params), TcwWanliExchangeRate.class);

		tcwWanliExchangeRateMapper.update(tcwWanliExchangeRate);
		return R.ok();
	}


	/**
	 * 刷新汇率
	 */
	@Override
	public R updateExchangeRate(String countTimeStart,String countTimeEnd) throws Exception{
		List<Map<String, Object>> tcwWanliExchangeRateList = new TcwWanliExchangeRate()
				.addField("D.Code AS code")//收款平台账号编码
				.addField("D.Id AS depositPlatformId")//收款平台账号id
				.addField("D.Mid AS depositPlatformMid")
				.addLeftJoin("TCW_DepositPlatform D ON D.Code = A.DepositPlatformCode")
				.setStatus(1)
				.queryMap();
		if(tcwWanliExchangeRateList!=null && tcwWanliExchangeRateList.size()>0){
			getExchangeRateByList(tcwWanliExchangeRateList,true,countTimeStart,countTimeEnd);
			return R.ok();
		}else {
			return R.error("未查询到汇率表信息");
		}
	}


	/**
	 * 根据收款平台信息mid刷新汇率

	@Override
	public R updateExchangeRateByMid(String code) throws Exception{
		//获取收款平台信息
		List<Map<String, Object>> tcwWanliExchangeRateList = new TcwWanliExchangeRate()
				.addField("D.Code AS code")//收款平台账号编码
				.addField("D.Id AS depositPlatformId")//收款平台账号id
				.addField("D.Mid AS depositPlatformMid")
				.addLeftJoin("TCW_DepositPlatform D ON D.Code = A.DepositPlatformCode")
				.setStatus(1)
				.setDepositPlatformCode(code)
				.queryMap();
		if(tcwWanliExchangeRateList!=null && tcwWanliExchangeRateList.size()>0){
			getExchangeRateByList(tcwWanliExchangeRateList,true);
			return R.ok();
		}else {
			return R.error("未查询到汇率表信息");
		}
	}*/

	/**
	 * 获取所有汇率计算需要参数的统计信息
	 */
	public List<TcwWanliExchangeRate> getExchangeRateByList(List<Map<String, Object>> tcwWanliExchangeRateList,boolean isUpdate,String countTimeStart,String countTimeEnd){
		//获取日期后一天
		String startDate = DateUtil.getYYYY_MM_DD(DateUtil.addDays(countTimeStart,1)) ;
		String endDate = DateUtil.getYYYY_MM_DD(DateUtil.addDays(countTimeEnd,1)) ;
		String startTime = startDate+" 00:00:00";//统计的开始时间
		String endTime = endDate+" 23:59:59";//统计的结束时间
		Date refreshTime = new Date();
		//获取统计数据
		//万里汇货币兑换单：兑出金额（CNY）---仅兑换CNY的部分
		List<Map<String, Object>> currencyExchangeByCny = financeMapper.currencyExchangeByCny(startTime,endTime,TcwWanliPayoutEnum.Type.TCW_WANLICURRENCYEXCHANGE.value);
		//万里汇提款单：汇入金额（CNY）
		List<Map<String, Object>> wanliDrawingByCny = financeMapper.wanliDrawingByCny(startTime,endTime,TcwWanliPayoutEnum.Type.TCW_WANLIDRAWING.value);
		//万里汇CNY付款单：汇入金额（CNY）
		List<Map<String, Object>> cnyPaymentByCny = financeMapper.cnyPaymentByCny(startTime, endTime, TcwWanliPayoutEnum.Type.TCW_WANLICNYPAYMENT.value);
		//万里汇预付款退回：退回金额（CNY）
		List<Map<String, Object>> paymentReturnByCny = financeMapper.paymentReturnByCny(startTime, endTime,TcwWanliPayoutEnum.Type.TCW_WANLIPAYMENTRETURN.value);
		List<TcwWanliExchangeRate> listByNew = new ArrayList<>();
		if(isUpdate){
			//修改旧数据状态=》0
			financeMapper.updateWanliExchangeRateStatus();
		}
		for(Map<String, Object> item : tcwWanliExchangeRateList){
			TcwWanliExchangeRate tcwWanliExchangeRate = countExchangeRate(item,currencyExchangeByCny,wanliDrawingByCny,cnyPaymentByCny,paymentReturnByCny);
			//刷新时间
			tcwWanliExchangeRate.setRefreshTime(refreshTime);
			tcwWanliExchangeRate.setCountTimeStart(startDate);
			tcwWanliExchangeRate.setCountTimeEnd(endDate);
			if(isUpdate){
				tcwWanliExchangeRate.setStatus(1);
				//tcwWanliExchangeRateMapper.update(tcwWanliExchangeRate);
				//新增
				tcwWanliExchangeRateMapper.insert(tcwWanliExchangeRate);
			}
			listByNew.add(tcwWanliExchangeRate);
		}
		return listByNew;
	}

	/**
	 * 计算汇率
	 */
	//********分子（之和） :
	//万里汇货币兑换单：兑入金额（CNY）---仅兑换CNY的部分
	//万里汇提款单：汇入金额（CNY）
	//万里汇CNY付款单：汇入金额（CNY）
	//万里汇预付款退回：退回金额（CNY）
	//********分母（之和）
	//万里汇货币兑换单：兑出金额（外币）---仅兑换CNY的部分
	//万里汇提款单：汇出金额（外币） ----不是万里汇减少的金额，务必确认这笔费用不算手续费
	//万里汇CNY付款单：汇出金额（外币） ---- 不是万里汇减少的金额，务必确认这笔费用不算手续费
	//万里汇预付款退回：支付币种金额（外币） ---- 不是万里汇减少的金额，务必确认这笔费用不算手续费
	public TcwWanliExchangeRate countExchangeRate(Map<String, Object> params,
												  List<Map<String, Object>> currencyExchangeByCny,
												  List<Map<String, Object>> wanliDrawingByCny,
												  List<Map<String, Object>> cnyPaymentByCny,
												  List<Map<String, Object>> paymentReturnByCny){

		String currencyCode = params.get("currencyCode").toString();//币种
		String depositPlatformMid = params.get("depositPlatformMid").toString();//收款平台账号Mid
		String depositPlatformCode = params.get("code").toString();//收款平台账号code
		Long depositPlatformId = Long.parseLong(params.get("depositPlatformId").toString());//收款平台账号id

		logger.info("更新汇率，平台Mid："+depositPlatformMid+"；币种："+currencyCode);
		logger.info("万里汇货币兑换单 *** 统计数据："+currencyExchangeByCny);
		logger.info("万里汇提款单 *** 统计数据："+wanliDrawingByCny);
		logger.info("万里汇CNY付款单 *** 统计数据："+cnyPaymentByCny);
		logger.info("万里汇预付款退回 *** 统计数据："+paymentReturnByCny);

		BigDecimal exchangeRate = BigDecimal.ZERO;//汇率
		BigDecimal amountTotalByCny = BigDecimal.ZERO;//分子
		BigDecimal amountTotalByOther = BigDecimal.ZERO;//分母

		//获取对应平台，对应币种的统计信息
		//万里汇货币兑换单
		if(currencyExchangeByCny!=null && currencyExchangeByCny.size()>0){
			List<Map<String, Object>> newByCondition = currencyExchangeByCny.stream()
					.filter(item->item.get("depositAccountId").equals(depositPlatformId) && item.get("currency").equals(currencyCode))
					.collect(Collectors.toList());
			if(newByCondition.size()>0){
				if(checkUtil.isNotNullByObject(newByCondition.get(0).get("amountTotalByCny")) &&
						checkUtil.isNotNullByObject(newByCondition.get(0).get("amountTotalByOther"))){
					BigDecimal amount = new BigDecimal(newByCondition.get(0).get("amountTotalByCny").toString());
					amountTotalByCny = amountTotalByCny.add(amount);
					BigDecimal amountByOther = new BigDecimal(newByCondition.get(0).get("amountTotalByOther").toString());
					amountTotalByOther = amountTotalByOther.add(amountByOther);
				}
				/*
				if(checkUtil.isNotNullByObject(newByCondition.get(0).get("amountTotalByOther"))){
					BigDecimal amount = new BigDecimal(newByCondition.get(0).get("amountTotalByOther").toString());
					amountTotalByOther = amountTotalByOther.add(amount);
				}
				 */
			}
		}

		//万里汇提款单
		if(wanliDrawingByCny!=null && wanliDrawingByCny.size()>0){
			List<Map<String, Object>> newByCondition = wanliDrawingByCny.stream()
					.filter(item->item.get("depositPlatformCode").equals(depositPlatformCode) && item.get("currency").equals(currencyCode))
					.collect(Collectors.toList());
			if(newByCondition.size()>0){
				if(checkUtil.isNotNullByObject(newByCondition.get(0).get("amountTotalByCny")) &&
						checkUtil.isNotNullByObject(newByCondition.get(0).get("amountTotalByOther"))){
					BigDecimal amount = new BigDecimal(newByCondition.get(0).get("amountTotalByCny").toString());
					amountTotalByCny = amountTotalByCny.add(amount);
					BigDecimal amountByOther = new BigDecimal(newByCondition.get(0).get("amountTotalByOther").toString());
					amountTotalByOther = amountTotalByOther.add(amountByOther);
				}
				/*
				if(checkUtil.isNotNullByObject(newByCondition.get(0).get("amountTotalByOther"))){
					BigDecimal amount = new BigDecimal(newByCondition.get(0).get("amountTotalByOther").toString());
					amountTotalByOther = amountTotalByOther.add(amount);
				}
				 */
			}
		}

		//万里汇CNY付款单
		if(cnyPaymentByCny!=null && cnyPaymentByCny.size()>0){
			List<Map<String, Object>> newByCondition = cnyPaymentByCny.stream()
					.filter(item->item.get("depositPlatformCode").equals(depositPlatformCode) && item.get("currency").equals(currencyCode))
					.collect(Collectors.toList());
			if(newByCondition.size()>0){
				if(checkUtil.isNotNullByObject(newByCondition.get(0).get("amountTotalByCny")) &&
						checkUtil.isNotNullByObject(newByCondition.get(0).get("amountTotalByOther"))){
					BigDecimal amount = new BigDecimal(newByCondition.get(0).get("amountTotalByCny").toString());
					amountTotalByCny = amountTotalByCny.add(amount);
					BigDecimal amountByOther = new BigDecimal(newByCondition.get(0).get("amountTotalByOther").toString());
					amountTotalByOther = amountTotalByOther.add(amountByOther);
				}
				/*
				if(checkUtil.isNotNullByObject(newByCondition.get(0).get("amountTotalByOther"))){
					BigDecimal amount = new BigDecimal(newByCondition.get(0).get("amountTotalByOther").toString());
					amountTotalByOther = amountTotalByOther.add(amount);
				}
				 */
			}
		}

		//万里汇预付款退回
		if(paymentReturnByCny!=null && paymentReturnByCny.size()>0){
			List<Map<String, Object>> newByCondition = paymentReturnByCny.stream()
					.filter(item->item.get("depositPlatformId").equals(depositPlatformId) && item.get("currency").equals(currencyCode))
					.collect(Collectors.toList());
			if(newByCondition.size()>0){
				if(checkUtil.isNotNullByObject(newByCondition.get(0).get("amountTotalByCny")) &&
						checkUtil.isNotNullByObject(newByCondition.get(0).get("amountTotalByOther"))){
					BigDecimal amount = new BigDecimal(newByCondition.get(0).get("amountTotalByCny").toString());
					amountTotalByCny = amountTotalByCny.add(amount);
					BigDecimal amountByOther = new BigDecimal(newByCondition.get(0).get("amountTotalByOther").toString());
					amountTotalByOther = amountTotalByOther.add(amountByOther);
				}
				/*
				if(checkUtil.isNotNullByObject(newByCondition.get(0).get("amountTotalByOther"))){
					BigDecimal amount = new BigDecimal(newByCondition.get(0).get("amountTotalByOther").toString());
					amountTotalByOther = amountTotalByOther.add(amount);
				}
				 */
			}
		}
		logger.info("分子："+amountTotalByCny+"；分母："+amountTotalByOther);
		//计算
		if(amountTotalByOther.compareTo(BigDecimal.ZERO)!=0 && amountTotalByCny.compareTo(BigDecimal.ZERO)!=0){
			exchangeRate = amountTotalByCny.divide(amountTotalByOther,5,BigDecimal.ROUND_HALF_UP);//四舍五入保留5位小数
		}
		TcwWanliExchangeRate tcwWanliExchangeRate = JSON.parseObject(JSON.toJSONString(params), TcwWanliExchangeRate.class);
		if(currencyCode.equals("CNH")){//离岸人民币默认汇率为1
			exchangeRate = BigDecimal.ONE;
		}
		//汇率
		tcwWanliExchangeRate.setExchangeRate(exchangeRate);
		return tcwWanliExchangeRate;
	}


	/**
	 * 参数验证
	 *
	 */
	public String checkParams(Map<String, Object> params, Long menuId, Predicate<YsCol> notNullCondition) throws Exception {
		//获取pc字段数据
		List<YsCol> listField = new YsCol()
				.where("A.MenuId = "+menuId)
				.setOrderby("A.SortNo ASC")
				.queryList();
		//验证必填字段的非空；其他字段的长度限制、类型
		String backMsg = checkUtil.checkTableColLengthAndDataType("TCW_WanliExchangeRate",listField,params,notNullCondition);
		if(checkUtil.isNotNullByObject(params.get("countTimeStart")) && checkUtil.isNotNullByObject(params.get("countTimeEnd"))){
			if(DateUtil.compareToDates(params.get("countTimeStart").toString(), params.get("countTimeEnd").toString())>0){
				backMsg = "开始时间要早于结束时间";
			}
		}
		return backMsg;
	}



	/**
	 * 每天定时新增汇率表
	 */
	public R addByEveryDay() throws Exception{
		//获取昨天数据，即为状态为1的数据
		List<TcwWanliExchangeRate> oldList = new TcwWanliExchangeRate().setStatus(1).queryList();
		//修改昨天数据状态=》0
		financeMapper.updateWanliExchangeRateStatus();
		Date refreshTime = new Date();
		for(TcwWanliExchangeRate oldItem:oldList){
			oldItem.setRefreshTime(refreshTime);//刷新时间
			oldItem.setExchangeRate(BigDecimal.ZERO);//汇率归零
			oldItem.setStatus(1);
			tcwWanliExchangeRateMapper.insert(oldItem);
		}
		return R.ok();
	}



}
